package com.aispeech.redis;

import com.aispeech.utils.JsonUtils;
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisURI;
import io.lettuce.core.api.sync.RedisCommands;
import io.lettuce.core.pubsub.RedisPubSubListener;
import io.lettuce.core.pubsub.StatefulRedisPubSubConnection;
import io.lettuce.core.pubsub.api.sync.RedisPubSubCommands;
import io.netty.util.internal.StringUtil;

import java.io.Serializable;
import java.util.List;

public class DbMgr implements Serializable {
    private static DbMgr ins = new DbMgr();
    private RedisClient client;
    private volatile boolean initialized = false;

    private DbMgr() {
    }

    public static DbMgr Instance() {
        return ins;
    }

    public DbMgr initialize(String connectionString) {
        RedisURI uri = RedisURI.create(connectionString);
        return initialize(uri);
    }

    public DbMgr initialize(int dbno) {
        return initialize("127.0.0.1", 6379, dbno, null);
    }

    public DbMgr initialize() {
        return initialize("127.0.0.1", 6379, 0, null);
    }

    public DbMgr initialize(String host, int port, int dbno, String password) {
        RedisURI.Builder builder = RedisURI
                .builder()
                .withHost(host)
                .withPort(port)
                .withDatabase(dbno);

        if (!StringUtil.isNullOrEmpty(password))
            builder.withPassword(password);

        return initialize(builder.build());
    }

    public DbMgr initialize(RedisURI uri) {
        client = RedisClient.create(uri);
        initialized = true;
        return this;
    }

    public RedisCommands<String, String> command() {
        return client.connect().sync();
    }

    public <T> T get(String key, Class<T> clz) {
        return JsonUtils.fastParse(command().get(key), clz);
    }

    public <T> T hget(String key, String field, Class<T> clz) {
        return JsonUtils.fastParse(command().hget(key, field), clz);
    }

    public String hget(String key, String field) {
        return command().hget(key, field);
    }

    public Long hdel(String key, String... field) {
        return command().hdel(key, field);
    }

    public <T> Boolean hset(String key, String field, T value) {
        return command().hset(key, field, String.valueOf(value));
    }

    public <T> T zpopmax(String key, Class<T> clz) {
        String value = command().zpopmax(key).getValue();

        if (clz == String.class) {
            return (T)value;
        } else {
            return JsonUtils.fastParse(value, clz);

        }
    }

	public List<String> zrange(String key, long start, long stop) {
		return command().zrange(key, start, stop);
	}

    public void destroy() {
        client.shutdown();
    }

    public boolean Initialized() {
        return initialized;
    }
}
